home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * quatern.c
- *
- * This module implements Quaternion algebra julia fractals.
- *
- * This file was written by Pascal Massimino.
- * Revised and updated for POV-Ray 3.x by Tim Wegner
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "fractal.h"
- #include "quatern.h"
- #include "spheres.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
- #ifndef Fractal_Tolerance
- #define Fractal_Tolerance 1e-8
- #endif
-
- #define Deriv_z2(n1,n2,n3,n4) \
- { \
- tmp = (n1)*x - (n2)*y - (n3)*z - (n4)*w; \
- (n2) = (n1)*y + x*(n2); \
- (n3) = (n1)*z + x*(n3); \
- (n4) = (n1)*w + x*(n4); \
- (n1) = tmp; \
- }
-
- #define Deriv_z3(n1,n2,n3,n4) \
- { \
- dtmp = 2.0*((n2)*y + (n3)*z + (n4)*w); \
- dtmp2 = 6.0*x*(n1) - dtmp; \
- (n1) = ( (n1)*x3 - x*dtmp )*3.0; \
- (n2) = (n2)*x4 + y*dtmp2; \
- (n3) = (n3)*x4 + z*dtmp2; \
- (n4) = (n4)*x4 + w*dtmp2; \
- }
-
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- int Iteration_z3(point, Julia)
- VECTOR point;
- FRACTAL * Julia;
- {
- int i;
- DBL x, y, z, w;
- DBL d, x2, tmp;
- DBL Exit_Value;
-
- Sx[0] = x = point[X];
- Sy[0] = y = point[Y];
- Sz[0] = z = point[Z];
- Sw[0] = w = (Julia->SliceDist
- - Julia->Slice[X]*x
- - Julia->Slice[Y]*y
- - Julia->Slice[Z]*z)/Julia->Slice[T];
-
- Exit_Value = Julia->Exit_Value;
-
- for (i = 1; i <= Julia->n; ++i)
- {
- d = y * y + z * z + w * w;
-
- x2 = x * x;
-
- if ((d + x2) > Exit_Value)
- {
- return (FALSE);
- }
-
- tmp = 3.0 * x2 - d;
-
- Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
- Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
- Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
- Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
- }
-
- return (TRUE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- int Iteration_Julia(point, Julia)
- VECTOR point;
- FRACTAL * Julia;
- {
- int i;
- DBL x, y, z, w;
- DBL d, x2;
- DBL Exit_Value;
-
- Sx[0] = x = point[X];
- Sy[0] = y = point[Y];
- Sz[0] = z = point[Z];
- Sw[0] = w = (Julia->SliceDist
- - Julia->Slice[X]*x
- - Julia->Slice[Y]*y
- - Julia->Slice[Z]*z)/Julia->Slice[T];
-
- Exit_Value = Julia->Exit_Value;
-
- for (i = 1; i <= Julia->n; ++i)
- {
- d = y * y + z * z + w * w;
-
- x2 = x * x;
-
- if ((d + x2) > Exit_Value)
- {
- return (FALSE);
- }
-
- x *= 2.0;
-
- Sy[i] = y = x * y + Julia->Julia_Parm[Y];
- Sz[i] = z = x * z + Julia->Julia_Parm[Z];
- Sw[i] = w = x * w + Julia->Julia_Parm[T];
- Sx[i] = x = x2 - d + Julia->Julia_Parm[X];;
-
- }
-
- return (TRUE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * D_Iteration puts in *Dist a lower bound for the distance from *point to the
- * set
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- /*----------- Distance estimator + iterations ------------*/
-
- int D_Iteration_z3(point, Julia, Dist)
- VECTOR point;
- FRACTAL * Julia;
- DBL * Dist;
- {
- int i, j;
- DBL Norm, d;
- DBL xx, yy, zz;
- DBL x, y, z, w;
- DBL tmp, x2;
- DBL Exit_Value;
- DBL Pow;
-
- x = Sx[0] = point[X];
- y = Sy[0] = point[Y];
- z = Sz[0] = point[Z];
- w = Sw[0] = (Julia->SliceDist
- - Julia->Slice[X]*x
- - Julia->Slice[Y]*y
- - Julia->Slice[Z]*z)/Julia->Slice[T];
-
- Exit_Value = Julia->Exit_Value;
-
- for (i = 1; i <= Julia->n; i++)
- {
- d = y * y + z * z + w * w;
-
- x2 = x * x;
-
- if ((Norm = d + x2) > Exit_Value)
- {
- /* Distance estimator */
-
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
-
- Pow = 1.0 / 3.0;
-
- for (j = 1; j < i; ++j)
- {
- xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
- yy = x * Sy[j] + y * Sx[j] - z * Sw[j] + w * Sz[j];
- zz = x * Sz[j] + y * Sw[j] + z * Sx[j] - w * Sy[j];
- w = x * Sw[j] - y * Sz[j] + z * Sy[j] + w * Sx[j];
-
- x = xx;
- y = yy;
- z = zz;
-
- Pow /= 3.0;
- }
-
- *Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
-
- return (FALSE);
- }
-
- tmp = 3.0 * x2 - d;
-
- Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
- Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
- Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
- Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
- }
-
- *Dist = Precision;
-
- return (TRUE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- int D_Iteration_Julia(point, Julia, Dist)
- VECTOR point;
- FRACTAL * Julia;
- DBL * Dist;
- {
- int i, j;
- DBL Norm, d;
- DBL Exit_Value;
- DBL x, y, z, w;
- DBL xx, yy, zz, x2;
- DBL Pow;
-
- x = Sx[0] = point[X];
- y = Sy[0] = point[Y];
- z = Sz[0] = point[Z];
- w = Sw[0] = (Julia->SliceDist
- - Julia->Slice[X]*x
- - Julia->Slice[Y]*y
- - Julia->Slice[Z]*z)/Julia->Slice[T];
-
- Exit_Value = Julia->Exit_Value;
-
- for (i = 1; i <= Julia->n; i++)
- {
- d = y * y + z * z + w * w;
-
- x2 = x * x;
-
- if ((Norm = d + x2) > Exit_Value)
- {
- /* Distance estimator */
-
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
-
- Pow = 1.0 / 2.0;
-
- for (j = 1; j < i; ++j)
- {
- xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
- yy = x * Sy[j] + y * Sx[j] + w * Sz[j] - z * Sw[j];
- zz = x * Sz[j] + z * Sx[j] + y * Sw[j] - w * Sy[j];
- w = x * Sw[j] + w * Sx[j] + z * Sy[j] - y * Sz[j];
-
- x = xx;
- y = yy;
- z = zz;
-
- Pow /= 2.0;
- }
-
- *Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
-
- return (FALSE);
- }
-
- x *= 2.0;
-
- Sy[i] = y = x * y + Julia->Julia_Parm[Y];
- Sz[i] = z = x * z + Julia->Julia_Parm[Z];
- Sw[i] = w = x * w + Julia->Julia_Parm[T];
- Sx[i] = x = x2 - d + Julia->Julia_Parm[X];
-
- }
-
- *Dist = Precision;
-
- return (TRUE);
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * Provided the iterations sequence has been built, perform the computation of
- * the Normal
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- void Normal_Calc_z3(Result, N_Max, fractal)
- VECTOR Result;
- int N_Max;
- FRACTAL *fractal;
- {
- DBL
- n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
- n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
- n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
-
- DBL x, y, z, w;
- int i;
- DBL tmp, dtmp, dtmp2, x2, x3, x4;
-
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
-
- for (i = 1; i <= N_Max; i++)
- {
- tmp = y * y + z * z + w * w;
-
- x2 = x * x;
- x3 = x2 - tmp;
- x4 = 3.0 * x2 - tmp;
-
- Deriv_z3(n11, n12, n13, n14);
- Deriv_z3(n21, n22, n23, n24);
- Deriv_z3(n31, n32, n33, n34);
-
- x = Sx[i];
- y = Sy[i];
- z = Sz[i];
- w = Sw[i];
- }
-
- Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
- Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
- Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- void Normal_Calc_Julia(Result, N_Max, fractal)
- VECTOR Result;
- int N_Max;
- FRACTAL *fractal;
- {
- DBL
- n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
- n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
- n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
- DBL tmp;
- DBL x, y, z, w;
- int i;
-
- x = Sx[0];
- y = Sy[0];
- z = Sz[0];
- w = Sw[0];
-
- for (i = 1; i <= N_Max; i++)
- {
- Deriv_z2(n11, n12, n13, n14);
- Deriv_z2(n21, n22, n23, n24);
- Deriv_z2(n31, n32, n33, n34);
-
- x = Sx[i];
- y = Sy[i];
- z = Sz[i];
- w = Sw[i];
- }
-
- Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
- Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
- Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Pascal Massimino
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Dec 1994 : Creation.
- *
- ******************************************************************************/
-
- int F_Bound_Julia(Ray, Fractal, Depth_Min, Depth_Max)
- RAY *Ray;
- FRACTAL *Fractal;
- DBL *Depth_Min, *Depth_Max;
- {
- return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
- }
-